package cn.backpackerxl.web.util;

import cn.backpackerxl.web.annotation.WebController;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Author:backpackerxl CreateTime:2022/4/17
 * FileName:ScanController
 **/
public class ScanController {
    public static Set<Class<?>> getController() {

        Set<Class<?>> controller = new HashSet<>();
        try {
            InputStream inputStream = ScanController.class.getClassLoader().getResourceAsStream("config.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            Set<Class<?>> controller1 = getClasses(properties.getProperty("controller"));
            for (Class<?> clazz : controller1) {
                if (clazz.isAnnotationPresent(WebController.class)) {
                    controller.add(clazz);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return controller;
    }

    /**
     * 获得所有的Controller
     *
     * @param pack
     * @return
     */
    public static Set<Class<?>> getClasses(String pack) {
        Set<Class<?>> classes = new LinkedHashSet();
        String packageName = pack;
        String packageDirName = pack.replace(".", "/");
        boolean recursive = true;

        try {
            Enumeration dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

            while (dirs.hasMoreElements()) {
                URL url = (URL) dirs.nextElement();
                String protocol = url.getProtocol();
                if ("file".equals(protocol)) {
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    findClassesInPackageByFile(packageName, filePath, recursive, classes);
                } else if ("jar".equals(protocol)) {
                    System.out.println("jar类型的扫描");

                    try {
                        JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
                        Enumeration<JarEntry> entries = jar.entries();
                        findClassesInPackageByJar(packageName, entries, packageDirName, recursive, classes);
                    } catch (Exception var10) {
                        var10.printStackTrace();
                    }
                }
            }
        } catch (Exception var11) {
            var11.printStackTrace();
        }

        return classes;
    }

    /**
     * 通过jar包获得
     *
     * @param packageName
     * @param entries
     * @param packageDirName
     * @param recursive
     * @param classes
     */
    private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, boolean recursive, Set<Class<?>> classes) {
        while (entries.hasMoreElements()) {
            JarEntry entry = (JarEntry) entries.nextElement();
            String name = entry.getName();
            if (String.valueOf(name.charAt(0)).equals("/")) {
                name = name.substring(1);
            }

            if (name.startsWith(packageDirName)) {
                int idx = name.lastIndexOf("/");
                if (idx != 1) {
                    packageName = name.substring(0, idx).replace("/", ".");
                }

                if ((idx != -1 || recursive) && name.endsWith(".class") && !entry.isDirectory()) {
                    String className = name.substring(packageName.length() + 1, name.length() - 6);

                    try {
                        classes.add(Class.forName(packageName + "." + className));
                    } catch (Exception var10) {
                        var10.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * 通过文件获得
     *
     * @param packageName
     * @param filePath
     * @param recursive
     * @param classes
     */
    private static void findClassesInPackageByFile(String packageName, String filePath, boolean recursive, Set<Class<?>> classes) {
        File dir = new File(filePath);
        if (dir.exists() && dir.isDirectory()) {
            File[] dirFiles = dir.listFiles((filex) -> {
                return recursive && filex.isDirectory() || filex.getName().endsWith(".class");
            });
            File[] var6 = dirFiles;
            int var7 = dirFiles.length;

            for (int var8 = 0; var8 < var7; ++var8) {
                File file = var6[var8];
                if (file.isDirectory()) {
                    findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
                } else {
                    String className = file.getName().substring(0, file.getName().length() - 6);

                    try {
                        classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                    } catch (Exception var12) {
                        var12.printStackTrace();
                    }
                }
            }

        } else {
            System.out.println("此" + packageName + "包下没有任何文件");
        }
    }
}
